//
//  CJFile.swift
//  CJCore
//
//  Created by 陈警卫 on 2024-06-03.
//

import UIKit

// MARK: - 文件操作

open class CJFile: NSObject {
    
    /// 判断文件存在
    @objc static public func fileExist(_ path: String) -> Bool {
        let exist = FileManager.default.fileExists(atPath: path)
        return exist
    }
    
    /// 创建文件夹
    @discardableResult
    @objc static public func createFolder(_ path: String) -> Bool {
        let exist = fileExist(path)
        if exist {
            return true
        }
        do {
            try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true)
            return true
        } catch {
            print("[CJFile]创建文件夹失败\(error)")
            return false
        }
    }
    
    /// 删除文件夹
    @discardableResult
    @objc static public func removeFolder(_ path: String) -> Bool {
        let exist = fileExist(path)
        if exist {
            do {
                try FileManager.default.removeItem(atPath: path)
                return true
            } catch {
                print("[CJFile]删除文件夹失败\(error)")
                return false
            }
        } else {
            return true
        }
    }
    
    /// 创建文件
    @discardableResult
    @objc static public func createFile(_ path: String) -> Bool {
        // 判断文件夹路径 没有就创建
        let foldPath = (path as NSString).deletingLastPathComponent
        let comp = createFolder(foldPath)
        if !comp {
            print("[CJFile]创建文件失败")
            return false
        }
        let exist = fileExist(path)
        if exist {
            return true
        }
        let result = FileManager.default.createFile(atPath: path, contents: nil)
        if !result {
            print("[CJFile]创建文件失败")
        }
        return result
    }
    
    /// 删除文件
    @discardableResult
    @objc static public func removeFile(_ path: String) -> Bool {
        let exist = fileExist(path)
        if exist {
            do {
                try FileManager.default.removeItem(atPath: path)
                return true
            } catch {
                print("[CJFile]删除文件失败\(error)")
                return false
            }
        } else {
            return true
        }
    }
    
    /// 读取文件
    @objc static public func readFile(_ path: String) -> Data? {
        let exist = fileExist(path)
        if exist {
            let data = FileManager.default.contents(atPath: path)
            return data
        } else {
            return nil
        }
    }
    
    /// 写入文件
    /// value: Data/String/NSArray/NSDictionary
    @discardableResult
    @objc static public func writeFile(_ path: String, value: AnyObject, atomically: Bool = true) -> Bool {
        
        // 判断文件路径
        let exist = fileExist(path)
        if !exist {
            createFile(path)
        }
        
        if value is String {
            if let temp = value as? String {
                do {
                    try temp.write(toFile: path, atomically: true, encoding: .utf8)
                    return true
                } catch {
                    print("[CJFile]写入文件失败\(error)")
                    return false
                }
            }
        } else if value is NSArray {
            if let temp = value as? NSArray {
                let result = temp.write(toFile: path, atomically: true)
                if !result {
                    print("[CJFile]写入文件失败")
                }
            }
        } else if value is NSDictionary {
            if let temp = value as? NSDictionary {
                let result = temp.write(toFile: path, atomically: true)
                if !result {
                    print("[CJFile]写入文件失败")
                }
            }
        } else if value is UIImage {
            if let temp = value as? UIImage, let tempData = temp.pngData() {
                do {
                    try tempData.write(to: URL(fileURLWithPath: path))
                    return true
                } catch {
                    print("[CJFile]写入文件失败\(error)")
                    return false
                }
            }
        }
        return false
    }
}

// MARK: - 文件路径

public extension CJFile {
    
    /// Home path
    @objc static var homePath: String {
        let homePath = NSHomeDirectory()
        return homePath
    }
    
    /// Document path
    @objc static var documentsPath: String {
        let documentsPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        return documentsPaths[0]
    }
    
    /// Library path
    @objc static var libraryPath: String {
        let libraryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)
        return libraryPath[0]
    }
    
    /// Preferences path
    @objc static var preferencesPath: String {
        let preferencesPath = libraryPath + "/Preferences"
        return preferencesPath
    }
    
    /// Caches path
    @objc static var cachesPath: String {
        let cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)
        return cachesPath[0]
    }
    
    /// tmp path
    @objc static var tmpPath: String {
        let tmpPath = homePath + "/tmp"
        return tmpPath
    }
}

// MARK: - 文件处理

open class CJFileHandle: NSObject {
    
    /// 数据写入文件
    @discardableResult
    @objc static public func write(_ path: String, value: String) -> Bool {
        if let data = value.data(using: .utf8) {
            return write(path, data: data)
        }
        return false
    }
    
    /// 数据写入文件
    @discardableResult
    @objc static public func write(_ path: String, data: Data) -> Bool {
        // 判断文件路径
        let exist = CJFile.fileExist(path)
        if !exist {
            CJFile.createFile(path)
        }
        do {
            let fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: path))
            fileHandle.seekToEndOfFile()
            fileHandle.write(data)
            try fileHandle.synchronize()
            fileHandle.closeFile()
            return true
        } catch {
            print("[CJFileHandle]数据写入文件失败\(error)")
            return false
        }
    }
}

